package org.weasel.data;

import java.io.IOException;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;

import org.jdom.Element;
import org.weasel.business.Developer;
import org.weasel.business.Iteration;
import org.weasel.business.Project;
import org.weasel.business.Release;
import org.weasel.business.Task;
import org.weasel.business.Unscheduled;
import org.weasel.business.UserStory;
import org.weasel.business.Utilities;

public class ProjectManager {
	private XMLManager xmlMan;
	private Project project;

	public ProjectManager(Project project) throws Exception {
		this.project = project;
		this.xmlMan = new XMLManager(project.getPath());
		if(!Utilities.existsFile(project.getPath())){
			//create root
			xmlMan.createRootElement("project");
			
			//add basic elements
			Element projectIdEl = new Element("id");
			projectIdEl.setText(project.getId());
			Element projectNameEl = new Element("name");
			projectNameEl.setText(project.getName());
			
			xmlMan.addElement(xmlMan.getRootElement(), projectIdEl);
			xmlMan.addElement(xmlMan.getRootElement(), projectNameEl);
			xmlMan.addElement(xmlMan.getRootElement(), new Element("developers"));
			xmlMan.addElement(xmlMan.getRootElement(), new Element("releases"));
			save();

			//add unscheduled part
			Unscheduled unsch = createUnscheduled(project.getId());
			project.setUnscheduled(unsch);
		}else{
			project.setReleases(getReleases());
			project.setUnscheduled(getUnscheduled());
		}
	}
	

	public Release createRelease(String name) throws Exception{
		String uniqueID = Utilities.createUniqueId();
		Element releaseEl = new Element("release");
		Element idEl = new Element("id");
		idEl.setText(uniqueID);
		Element nameEl = new Element("name");
		nameEl.setText(name);
		Element iterationsEl = new Element("iterations");
		
		releaseEl.addContent(idEl);
		releaseEl.addContent(nameEl);
		releaseEl.addContent(iterationsEl);
		
		Element parent = xmlMan.getRootElement();
		xmlMan.addElement(parent.getChild("releases"), releaseEl);
		save();
		
		//now add unscheduled object since the parent Release has to be present
		//in the xml-file already
		Unscheduled unsch = createUnscheduled(uniqueID);
		Release release = new Release(uniqueID, name, null, unsch, this);
		return release;
	}
	
	public void deleteRelease(String releaseID) throws Exception{
		xmlMan.removeParent(releaseID);
		save();
	}
	
	public Release getRelease(String releaseID) throws Exception{
		Element releaseEl = xmlMan.getElement(releaseID);
		String id = releaseEl.getChildText("id");
		String name = releaseEl.getChildText("name");
		
		//get iterationslist
		ArrayList<Iteration> iterations = new ArrayList<Iteration>();
		List<Element> iterationsElementList = releaseEl.getChild("iterations").getChildren();
		for (Element element : iterationsElementList) {
			Iteration iteration = getIteration(element.getChildText("id"));
			iterations.add(iteration);
		}
		
		Unscheduled unsch = getUnscheduled(releaseEl.getChild("unscheduled").getChildText("id"));
		Release release = new Release(id, name, iterations, unsch, this);
		
		return release;
	}
	
	public ArrayList<Release> getReleases() throws Exception{
		Element releasesElement = xmlMan.getRootElement().getChild("releases");
		ArrayList<Release> releases = new ArrayList<Release>();
		
		List<Element> releaseElementList = releasesElement.getChildren();
		for (Element element : releaseElementList) {
			Release r = getRelease(element.getChildText("id"));
			releases.add(r);
		}
		return releases;
	}
	
	/**
	 * creates and returns an object of type Iteration and writes it
	 * simultaneously into the correct XML-file
	 * @param name
	 * @return
	 * @throws Exception 
	 */
	public Iteration createIteration(String releaseID, String name) throws Exception{
		//name should be enough, since we do not have a list of
		//userstories in the beginning
		String uniqueID = Utilities.createUniqueId();
		Element iterationEl = new Element("iteration");
		Element idEl = new Element("id");
		idEl.setText(uniqueID);
		Element nameEl = new Element("name");
		nameEl.setText(name);
		
		//create the element that holds the list of user-stories
		Element userstoriesEl = new Element("userstories");
		
		iterationEl.addContent(idEl);
		iterationEl.addContent(nameEl);
		iterationEl.addContent(userstoriesEl);
		
		//get the parent element release using releaseID
		Element releaseEl = xmlMan.getElement(releaseID);
		xmlMan.addElement(releaseEl.getChild("iterations"), iterationEl);
		
		Iteration iteration = new Iteration(uniqueID, name, null, this);
		save();
		return iteration;
	}
	
	/**
	 * Deletes a Iteration element from the XML file
	 * @param iterID
	 * @throws Exception 
	 */
	public void deleteIteration(String iterID) throws Exception{
		xmlMan.removeParent(iterID);
		save();
	}
	
	/**
	 * Returns a specific Iteration object, read out of the XML file
	 * @param iterID
	 * @return
	 * @throws Exception 
	 */
	public Iteration getIteration(String iterID) throws Exception{
		Element iterationEl = xmlMan.getElement(iterID);
		String id = iterationEl.getChildText("id");
		String name = iterationEl.getChildText("name");
		//load userstories
		ArrayList<UserStory> userstories = new ArrayList<UserStory>();
		List<Element> userstoryElementList = iterationEl.getChild("userstories").getChildren();
		for (Element element : userstoryElementList) {
			UserStory story = getUserStory(element.getChildText("id"));
			userstories.add(story);
		}
		Iteration iteration = new Iteration(id, name, userstories, this);
		return iteration;
	}
	
	
	/**
	 * Don't use this method any more!!!
	 */
	@Deprecated
	public UserStory createUserStory(String name, int businessValue, Time estimatedTime, Time usedTime, int effort) throws Exception {
		String uniqueId = Utilities.createUniqueId();
		
		//create the tags needed for the UserStory
		Element userStoryEl = new Element("userstory");
		Element idEl = new Element("id");
		idEl.setText(uniqueId);
		
		Element nameEl = new Element("name");
		nameEl.setText(name);
		
		Element businessEl = new Element("businessValue");
		businessEl.setText(String.valueOf(businessValue));
		
		Element estimatedTimeEl = new Element("estimatedTime");
		estimatedTimeEl.setText(String.valueOf(estimatedTime));
		
		Element usedTimeEl = new Element("usedTime");
		usedTimeEl.setText(String.valueOf(usedTime));
		
		Element effortEl = new Element("effort");
		effortEl.setText(String.valueOf(effort));
		
		Element taskListEl = new Element("tasks");
		//do not fill initially
		
		Element developerListEl = new Element("developers");
		//do not fill initially
		
		userStoryEl.addContent(idEl);
		userStoryEl.addContent(nameEl);
		userStoryEl.addContent(businessEl);
		userStoryEl.addContent(estimatedTimeEl);
		userStoryEl.addContent(usedTimeEl);
		userStoryEl.addContent(effortEl);
		userStoryEl.addContent(taskListEl);
		userStoryEl.addContent(developerListEl);
		
		//write into the XML file
		//get the element of unscheduled area
		Element unscheduled;
		try {
			unscheduled = xmlMan.getElementByQuery("/descendant::unscheduled");
			xmlMan.addElement(unscheduled, userStoryEl);
		} catch (Exception e) {
			throw e;
		}
		
		//if everthing is fine
		UserStory story = new UserStory(uniqueId, name, businessValue, estimatedTime, usedTime, effort, null, null);
		save();
		return story;
	}
	
	/**
	 * Overloaded method, used when moving userstory from unscheduled to specific iteration, e.g.
	 * remove userstory by using deleteUserStory(...) and then use this method passing it the ID
	 * of the element (being it an unscheduled one or iteration) where to move it
	 * @param elementID
	 * @param name
	 * @param businessValue
	 * @param estimatedTime
	 * @param usedTime
	 * @param effort
	 * @return
	 * @throws Exception
	 */
	public UserStory createUserStory(String elementID, String name, int businessValue, Time estimatedTime, Time usedTime, int effort) throws Exception {
		String uniqueId = Utilities.createUniqueId();
		
		//create the tags needed for the UserStory
		Element userStoryEl = new Element("userstory");
		Element idEl = new Element("id");
		idEl.setText(uniqueId);
		
		Element nameEl = new Element("name");
		nameEl.setText(name);
		
		Element businessEl = new Element("businessValue");
		businessEl.setText(String.valueOf(businessValue));
		
		Element estimatedTimeEl = new Element("estimatedTime");
		estimatedTimeEl.setText(String.valueOf(estimatedTime));
		
		Element usedTimeEl = new Element("usedTime");
		usedTimeEl.setText(String.valueOf(usedTime));
		
		Element effortEl = new Element("effort");
		effortEl.setText(String.valueOf(effort));
		
		Element taskListEl = new Element("tasks");
		//do not fill initially
		
		Element developerListEl = new Element("developers");
		//do not fill initially
		
		userStoryEl.addContent(idEl);
		userStoryEl.addContent(nameEl);
		userStoryEl.addContent(businessEl);
		userStoryEl.addContent(estimatedTimeEl);
		userStoryEl.addContent(usedTimeEl);
		userStoryEl.addContent(effortEl);
		userStoryEl.addContent(taskListEl);
		userStoryEl.addContent(developerListEl);
		
		//write into the XML file
		//get the element of unscheduled area
		Element parent = xmlMan.getElement(elementID);
		xmlMan.addElement(parent.getChild("userstories"), userStoryEl);
		
		//if everthing is fine
		UserStory story = new UserStory(uniqueId, name, businessValue, estimatedTime, usedTime, effort, null, null);
		save();
		return story;
	}
	
	/**
	 * Deletes a UserStory element from the XML-file
	 * @param userStoryID
	 * @throws Exception 
	 */
	public void deleteUserStory(String userStoryID) throws Exception {
		xmlMan.removeParent(userStoryID);
		save();
	}
	
	/**
	 * Returns an object of type UserStory, read out of the XML file
	 * @param userStoryID
	 * @return
	 * @throws Exception 
	 */
	public UserStory getUserStory(String userStoryID) throws Exception {
		//get the XML element first
		Element userStoryEl = xmlMan.getElement(userStoryID);
		String id = userStoryEl.getChild("id").getText();
		String name = userStoryEl.getChild("name").getText();;
		int businessVal = Integer.parseInt(userStoryEl.getChild("businessValue").getText());
		Time estimatedT = Time.valueOf(userStoryEl.getChild("estimatedTime").getText());
		Time usedT = Time.valueOf(userStoryEl.getChild("usedTime").getText());
		int effort = Integer.parseInt(userStoryEl.getChild("effort").getText());
		
		//load tasks
		ArrayList<Task> tasks = new ArrayList<Task>();
		List<Element> taskElementList = userStoryEl.getChild("tasks").getChildren();
		for (Element element : taskElementList) {
			String taskID = element.getChild("id").getText();
			String taskDesc = element.getChild("description").getText();
			String isCompletedTmp = element.getChild("isCompleted").getText();
			String taskDeveloper = element.getChild("developerID").getText();
			//get a developer object with its ID
			//Developer d = getDeveloper(taskDeveloper);
			boolean isCompleted = false;
			if(isCompletedTmp.equals("true")) {
				isCompleted = true;
			} 
			
			Task t = new Task(taskID, taskDesc, isCompleted);
			tasks.add(t);
		}
		
		//load developers assigned to the userstory
		ArrayList<Developer> developers = new ArrayList<Developer>();
		List<Element> developerElementList = userStoryEl.getChild("developers").getChildren();
		for (Element element : developerElementList) {
			String developerID = element.getChild("developerID").getText();
			Developer tmp = project.getDeveloper(developerID);
			developers.add(tmp);
		}
		
		//create the object
		UserStory story = new UserStory(id, name, businessVal, estimatedT, usedT, effort, developers, tasks);
		return story;
	}
	
	public void addDeveloper(String developerID) throws Exception{
		Element developerEl = new Element("developerID");
		developerEl.setText(developerID);

		//retrieve the parent element "developers" where to attach the developer node
		Element parent = xmlMan.getRootElement().getChild("developers");
		xmlMan.addElement(parent, developerEl);
		
		save();
	}
	
	public void deleteDeveloper(String developerID) throws Exception{
		xmlMan.removeElement(developerID);
		save();
	}
	/*
	public Developer getDeveloper(String developerID) throws Exception{
		Element developerEl = xmlMan.getElement(developerID);
		String id = developerEl.getChildText("id");
		String name = developerEl.getChildText("name");
		String mail = developerEl.getChildText("email");
		String position = developerEl.getChildText("position");
		
		Developer developer = new Developer(id, name, mail, position);
		return developer;
	}
	*/
	
	public ArrayList<String> getDeveloperIDs() throws Exception{
		ArrayList<String> developers = new ArrayList<String>();
		List<Element> developerElementList = xmlMan.getRootElement().getChild("developers").getChildren();
		for (Element element : developerElementList) {
			developers.add( element.getText());
		}
		return developers;
	}
	
	public Task createTask(String storyID, String description) throws Exception{
		String uniqueID = Utilities.createUniqueId();
		Element taskElement = new Element("task");
		Element idEl = new Element("id");
		idEl.setText(uniqueID);
		Element descriptionEl = new Element("description");
		descriptionEl.setText(description);
		Element developerIDEl = new Element("developerID");
		Element completedEl = new Element("isCompleted");
		completedEl.setText("false");
		
		taskElement.addContent(idEl);
		taskElement.addContent(descriptionEl);
		taskElement.addContent(developerIDEl);
		taskElement.addContent(completedEl);
		
		//get parent
		Element parent = xmlMan.getElement(storyID).getChild("tasks");
		xmlMan.addElement(parent, taskElement);
		
		Task task = new Task(uniqueID, description, false);
		save();
		return task;
	}
	
	public void deleteTask(String taskID) throws Exception{
		xmlMan.removeParent(taskID);
		save();
	}
	
	public Task getTask(String taskID) throws Exception{
		Element taskEl = xmlMan.getElement(taskID);
		String id = taskEl.getChildText("id");
		String description = taskEl.getChildText("description");
		
		String isCompletedTmp = taskEl.getChildText("isCompleted");
		boolean isCompleted = false;
		if(isCompletedTmp!=null && isCompletedTmp.equals("true")) {
			isCompleted = true;
		}
		
		Task task = new Task(id, description, isCompleted);
		return task;
	}
	
	public Unscheduled createUnscheduled(String parentID) throws Exception{
		String uniqueID = Utilities.createUniqueId();
		Element unscheduledEl = new Element("unscheduled");
		Element idEl = new Element("id");
		idEl.setText(uniqueID);
		Element userstoriesEl = new Element("userstories");
		
		unscheduledEl.addContent(idEl);
		unscheduledEl.addContent(userstoriesEl);
		
		Element parent = xmlMan.getElement(parentID);
		xmlMan.addElement(parent, unscheduledEl);
		
		Unscheduled unsch = new Unscheduled(uniqueID, null, this);
		save();
		return unsch;
	}
	
	public Unscheduled getUnscheduled(String unscheduledID) throws Exception{
		Element unscheduledEl = xmlMan.getElement(unscheduledID);
		String id = unscheduledEl.getChildText("id");
		
		//get list of userstories
		ArrayList<UserStory> userstories = new ArrayList<UserStory>();
		List<Element> userstoriesElementList = unscheduledEl.getChild("userstories").getChildren();
		//convert into userstory objects
		for (Element element : userstoriesElementList) {
			UserStory story = getUserStory(element.getChildText("id"));
			userstories.add(story);
		}
		
		Unscheduled unsch = new Unscheduled(id, userstories, this);
		return unsch;
	}
	
	
	//TODO Test this method
	/**
	 * This method is needed for the initial loading of the unscheduled part of a project
	 * @throws Exception 
	 */
	public Unscheduled getUnscheduled() throws Exception {
		Element unscheduledEl = xmlMan.getElementByQuery("/descendant::unscheduled[last()]");
		String id = unscheduledEl.getChildText("id"); //not really necessary
		
		//get list of userstories
		ArrayList<UserStory> userstories = new ArrayList<UserStory>();
		List<Element> userstoriesElementList = unscheduledEl.getChild("userstories").getChildren();
		//convert into userstory objects
		for (Element element : userstoriesElementList) {
			UserStory story = getUserStory(element.getChildText("id"));
			userstories.add(story);
		}
		
		Unscheduled unsch = new Unscheduled(id, userstories, this);
		return unsch;
	}
	
	/**
	 * Saves the XML file
	 * @throws IOException
	 */
	private void save() throws IOException{
		xmlMan.writeToFile();
	}
	
}
